﻿using System;
using MugenInjection.Delegates;
using MugenInjection.Interface;

namespace MugenInjection.Syntax.Method
{
    /// <summary>
    /// Specific fluent syntax for method binding.
    /// </summary>
    public interface IMethodWhenSyntax : IBindingBuilder
    {
        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax When(CanResolveBindingDelegate canResolveBindingDelegate);

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenInto(System.Type type);

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenInto<TType>();

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenIntoIsAssignable(System.Type type);

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenIntoIsAssignable<TType>();

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenNamespaceEqual(string name);

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenClassHasAttribute(System.Type attributeType);

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="T">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax WhenClassHasAttribute<T>() where T : Attribute;
    }

    /// <summary>
    /// Specific fluent syntax for method binding.
    /// </summary>
    public interface IMethodWhenSyntax<T> : IBindingBuilder
    {
        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> When(
            CanResolveBindingDelegate canResolveBindingDelegate);

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenInto(System.Type type);

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenInto<TType>();

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenIntoIsAssignable(System.Type type);

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenIntoIsAssignable<TType>();

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenNamespaceEqual(string name);

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenClassHasAttribute(System.Type attributeType);

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="TAttribute">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T> WhenClassHasAttribute<TAttribute>() where TAttribute : Attribute;
    }
}